import 'dart:io';
import 'dart:convert' as convert;
import 'package:dio/dio.dart';
import 'package:dio/io.dart';
import 'package:flutter_ohos/app/common/global.dart';
import 'package:flutter_ohos/app/network/interceptor/log_interceptors.dart';
import 'package:flutter_ohos/app/routes/app_routes.dart';
import 'package:get/get.dart' hide Response;
import 'package:http_proxy/http_proxy.dart';

import '../common/widgets/loading.dart';
import 'base_response_entity.dart';
import 'http_config.dart';
import 'http_method.dart';
import 'interceptor/custom_interceptors.dart';

class HttpManage {
  static HttpManage? _instance;
  static Dio _dio = Dio();

  Dio get dio => _dio;

  HttpManage._internal() {
    _instance = this;
    _instance!._init();
  }

  factory HttpManage() => _instance ?? HttpManage._internal();

  static HttpManage getInstance() {
    _instance ?? HttpManage._internal();
    return _instance!;
  }

  static clear() {
    _instance = null;
  }

  static initNetwork() {
    if (_instance != null) {
      _instance!._init();
    }else {
      HttpManage._internal();
    }
  }

  ///初始化dio
  _init() async {
    Proxy.init();

    /// 初始化基本选项
    BaseOptions options = BaseOptions(
        baseUrl: HttpConfig.baseURL,
        connectTimeout: const Duration(milliseconds: HttpConfig.connectTimeout),
        receiveTimeout: const Duration(milliseconds: HttpConfig.receiveTimeout),
        sendTimeout: const Duration(milliseconds: HttpConfig.sendTimeout));

    /// 初始化dio
    _dio = Dio(options);
    _dio.interceptors.add(CustomInterceptors());
    if (!Global.isRelease) {
      _dio.interceptors.add(LogInterceptors());
    }
    // 在调试模式下需要抓包调试，所以我们使用代理，并禁用HTTPS证书校验
    (dio.httpClientAdapter as IOHttpClientAdapter).createHttpClient =
    // (dio.httpClientAdapter as DefaultHttpClientAdapter).onHttpClientCreate =
        () {
      var client = HttpClient();
      //代理工具会提供一个抓包的自签名证书，会通不过证书校验，所以我们禁用证书校验
      client.badCertificateCallback =
          (X509Certificate cert, String host, int port) => true;
      if (Proxy.isProxy) {
        client.findProxy = (uri) {
          // return 'PROXY 10.18.120.65:8888';
          /// return 'PROXY localhost:8888';
          return "PROXY ${Proxy.proxy?.host}:${Proxy.proxy?.port}";
        };
      }
      return client;
    };
  }

  /// 取消请求token
  final CancelToken _cancelToken = CancelToken();

  /// 请求类
  void request<T>(
    String path, {
    HttpMethod method = HttpMethod.get,
    Map<String, dynamic>? params,
    Map<String, dynamic>? headParams,
    data,
    CancelToken? cancelToken,
    Options? options,
    ProgressCallback? onSendProgress,
    ProgressCallback? onReceiveProgress,
    Function(T? t)? onSuccess,
    Function(BaseResponseEntity rawJson)? rawValueCallBack,
    Function(String errorCode, String errorMessage)? onError,
    bool loading: true,
  }) async {
    const methodValues = {
      HttpMethod.get: 'get',
      HttpMethod.post: 'post',
      HttpMethod.put: 'put',
      HttpMethod.delete: 'delete',
      HttpMethod.patch: 'patch',
      HttpMethod.head: 'head'
    };
    options ??= Options(method: methodValues[method]);
    if (headParams != null) {
      options.headers = headParams;
    }
    if (loading) {
      Loading.showLoading();
    }
    try {
      Response response;
      response = await _dio.request(path,
          data: data,
          queryParameters: params,
          cancelToken: cancelToken ?? _cancelToken,
          options: options,
          onSendProgress: onSendProgress,
          onReceiveProgress: onReceiveProgress);
      /// 拦截http层异常码
      if (response.statusCode == 200) {
          if (onSuccess != null) {
            /// 返回泛型Bean
            onSuccess(response.data);
          }

        /// 这里做baseBean泛型解析，封装 并拦截后台code异常码，可拦截自定义处理
        // if (response.data is String) {
        //   response.data = convert.jsonDecode(response.data);
        // }
        // BaseResponseEntity<T> bean = BaseResponseEntity.fromJson(response.data);
        // bean.rawJsonValue = (response.data as Map)["data"];

        // if (bean.code == 10000 || bean.code == "10000") {
        //   if (loading) {
        //     Loading.hideLoading();
        //   }
        //   if (rawValueCallBack != null) {
        //     rawValueCallBack(bean);
        //   }
        //   if (onSuccess != null) {
        //     /// 返回泛型Bean
        //     onSuccess(bean.data);
        //   }
        // } else {
        //   if (loading) {
        //     Loading.hideLoading();
        //   }
        //   if (onError != null) {
        //     onError(bean.code.toString(), bean.message);
        //   }
        //   ///token过期拦截,（特定的错误码可以自定义，这里我随便写的11111），跳转登录页
        //   if (bean.code == 11111) {
        //     Global.clearUserInfo();
        //     Get.offAllNamed(Routes.);
        //   }
        // }
      }
    } on DioException catch (e) {
      if (loading) {
        Loading.hideLoading();
      }
      throw e;
    } finally {
      if (loading) {
        Loading.hideLoading();
      }
    }
  }

  get<T>(String path, Map<String, dynamic>? params,
      {Function(T? t)? onSuccess,
      Function(BaseResponseEntity rawJson)? rawValueCallBack,
      Function(String errorCode, String errorMessage)? onError,
      bool loading: true}) async {
    request<T>(path,
        params: params,
        method: HttpMethod.get,
        onSuccess: onSuccess,
        rawValueCallBack: rawValueCallBack,
        onError: onError,
        loading: loading);
  }

  post<T>(String path, data,
      {Function(T? t)? onSuccess,
      Function(String errorCode, String errorMessage)? onError,
      Function(BaseResponseEntity rawJson)? rawValueCallBack,
      Map<String, dynamic>? headParams,
      bool loading: true}) async {
    request<T>(path,
        data: data,
        method: HttpMethod.post,
        onSuccess: onSuccess,
        rawValueCallBack: rawValueCallBack,
         headParams: headParams,
        onError: onError,
        loading: loading);
  }

  /// 取消网络请求
  void cancelRequests({CancelToken? token}) {
    token ?? _cancelToken.cancel("cancelled");
  }
}

class Proxy {
  static HttpProxy? proxy;
  static bool isProxy = false;

  static Future init() async {
    proxy ??= await HttpProxy.createHttpProxy();
    if (proxy!.host != null) {
      isProxy = true;
    }
  }
}
